import os
import re
import logging
from datetime import datetime
import json

# 设置日志
logger = logging.getLogger('cinema_utils')

class CinemaUtils:
    """
    本地影院工具类，提供本地视频资源的播放、列表和管理功能
    """
    
    # 默认资源目录
    DEFAULT_RESOURCE_DIR = '/app/skit'  
    
    # 支持的视频文件格式
    SUPPORTED_VIDEO_EXTENSIONS = [
        '.mp4', '.avi', '.mkv', '.mov', '.flv', 
        '.wmv', '.m4v', '.mpeg', '.mpg', '.webm'
    ]
    
    @classmethod
    def is_video_file(cls, filename):
        """
        判断文件是否为支持的视频文件
        
        参数:
            filename: 文件名
        
        返回:
            bool: 是视频文件返回True，否则返回False
        """
        ext = os.path.splitext(filename)[1].lower()
        return ext in cls.SUPPORTED_VIDEO_EXTENSIONS
    
    def list_videos(self, directory=None, search_query=''):
        """
        列出指定目录下的所有视频文件
        
        参数:
            directory: 要扫描的目录，默认为DEFAULT_RESOURCE_DIR
            search_query: 搜索关键词，用于过滤结果
        
        返回:
            list: 视频文件信息列表
        """
        if directory is None:
            directory = self.DEFAULT_RESOURCE_DIR
        
        videos = []
        
        try:
            for item in os.listdir(directory):
                item_path = os.path.join(directory, item)
                
                # 跳过隐藏文件/文件夹
                if item.startswith('.'):
                    continue
                
                # 如果是文件，检查是否为视频文件
                if os.path.isfile(item_path):
                    if self.is_video_file(item) and (not search_query or search_query.lower() in item.lower()):
                        videos.append({
                            'name': item,
                            'path': item_path,
                            'is_file': True,
                            'is_video': True,
                            'last_modified': os.path.getmtime(item_path),
                            'size': os.path.getsize(item_path),
                            'parent_dir': directory
                        })
                
                # 如果是文件夹，添加到结果中但不作为视频文件
                elif os.path.isdir(item_path):
                    if not search_query or search_query.lower() in item.lower():
                        videos.append({
                            'name': item,
                            'path': item_path,
                            'is_file': False,
                            'is_video': False,
                            'last_modified': os.path.getmtime(item_path),
                            'size': None,
                            'parent_dir': directory
                        })
            
            # 按名称排序
            videos.sort(key=lambda x: x['name'].lower())
            
        except Exception as e:
            logger.error(f"列出视频文件失败: {str(e)}")
            raise
        
        return videos
    
    def get_video_info(self, video_path):
        """
        获取视频文件的详细信息
        
        参数:
            video_path: 视频文件路径
        
        返回:
            dict: 视频信息字典
        """
        try:
            # 检查文件是否存在且是视频文件
            if not os.path.exists(video_path):
                return {'success': False, 'message': '文件不存在'}
            
            if not os.path.isfile(video_path) or not self.is_video_file(os.path.basename(video_path)):
                return {'success': False, 'message': '不是有效的视频文件'}
            
            # 获取文件基本信息
            stats = os.stat(video_path)
            file_size = stats.st_size
            last_modified = stats.st_mtime
            
            # 格式化文件大小
            def format_size(size_bytes):
                if size_bytes < 1024:
                    return f"{size_bytes} B"
                elif size_bytes < 1048576:
                    return f"{size_bytes/1024:.2f} KB"
                elif size_bytes < 1073741824:
                    return f"{size_bytes/1048576:.2f} MB"
                else:
                    return f"{size_bytes/1073741824:.2f} GB"
            
            # 检查同一目录下是否有配套的海报文件和nfo文件
            dir_path = os.path.dirname(video_path)
            base_name = os.path.splitext(os.path.basename(video_path))[0]
            
            # 查找海报文件
            poster_path = None
            poster_extensions = ['.jpg', '.jpeg', '.png', '.webp']
            for ext in poster_extensions:
                possible_poster = os.path.join(dir_path, f'{base_name}{ext}')
                if os.path.exists(possible_poster):
                    poster_path = possible_poster
                    break
            
            # 查找nfo文件
            nfo_path = os.path.join(dir_path, f'{base_name}.nfo')
            has_nfo = os.path.exists(nfo_path)
            
            return {
                'success': True,
                'data': {
                    'name': os.path.basename(video_path),
                    'path': video_path,
                    'size': file_size,
                    'size_formatted': format_size(file_size),
                    'last_modified': last_modified,
                    'last_modified_formatted': datetime.fromtimestamp(last_modified).strftime('%Y-%m-%d %H:%M:%S'),
                    'poster_path': poster_path,
                    'has_nfo': has_nfo,
                    'directory': dir_path
                }
            }
            
        except Exception as e:
            logger.error(f"获取视频信息失败: {str(e)}")
            return {'success': False, 'message': str(e)}
    
    def validate_file_path(self, file_path):
        """
        验证文件路径是否有效且是支持的视频文件
        
        参数:
            file_path: 文件路径
        
        返回:
            tuple: (是否有效, 消息)
        """
        # 安全检查，防止目录遍历攻击
        try:
            # 标准化路径
            normalized_path = os.path.normpath(file_path)
            
            # 检查文件是否存在
            if not os.path.exists(normalized_path):
                return False, '文件不存在'
            
            # 检查是否为文件
            if not os.path.isfile(normalized_path):
                return False, '路径不是文件'
            
            # 检查是否为支持的视频格式
            if not self.is_video_file(os.path.basename(normalized_path)):
                return False, '不支持的视频格式'
            
            # 检查文件是否在允许的目录下
            if not normalized_path.startswith(os.path.normpath(self.DEFAULT_RESOURCE_DIR)):
                return False, '文件不在允许的目录内'
            
            return True, '验证成功'
            
        except Exception as e:
            logger.error(f"验证文件路径失败: {str(e)}")
            return False, str(e)
    
    def scan_directory_recursive(self, directory=None):
        """
        递归扫描目录下的所有视频文件
        
        参数:
            directory: 要扫描的目录，默认为DEFAULT_RESOURCE_DIR
        
        返回:
            list: 所有视频文件路径列表
        """
        if directory is None:
            directory = self.DEFAULT_RESOURCE_DIR
        
        video_files = []
        
        try:
            for root, dirs, files in os.walk(directory):
                # 跳过隐藏目录
                dirs[:] = [d for d in dirs if not d.startswith('.')]
                
                for file in files:
                    if self.is_video_file(file):
                        video_path = os.path.join(root, file)
                        video_files.append(video_path)
            
        except Exception as e:
            logger.error(f"递归扫描目录失败: {str(e)}")
            raise
        
        return video_files